﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using J9Script;


namespace Example
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnExecute_Click(object sender, EventArgs e)
        {
            try
            {
                IScriptObject result = ScriptEvaluator.EvaluateNow(txtScript.Text);

                txtResult.Text = result.ToPrimitiveString();
            }
            catch (ScriptEvaluatorException ex)
            {
                txtResult.Text = ex.Message + "\r\n" + ex.Position.ToString() + "\r\n\r\n" + "Script Snippet:\r\n" + ex.ScriptSnippet;
            }
            catch (Exception ex)
            {
                txtResult.Text = ex.Message;
            }
        }

        private void btnSimpleExample_Click(object sender, EventArgs e)
        {
            // This example demonstrates executing a very simple script.

            System.Diagnostics.Debugger.Break();

            string script = "return 10 + 5;";

            IScriptObject result = ScriptEvaluator.EvaluateNow(script);

            System.Diagnostics.Debugger.Break(); // check result from above.
        }

        private void btnPredefinedVariablesExample_Click(object sender, EventArgs e)
        {
            // This example demonstrates passing predefined variables to the script and extracting them when complete.

            System.Diagnostics.Debugger.Break();

            ScriptVariableCollection vars = new ScriptVariableCollection();
            vars["name"] = new ScriptString("John Hughes"); // the script changes this to "Sam".
            vars["x"] = new ScriptNumber(19); // this does not change.
            vars["b"] = ScriptBoolean.True; // after the script runs, notice how the datatype of this will change from Boolean to DateTime.

            string script = "name = \"Sam\"; b = DateTime.Now;";

            IScriptObject result = ScriptEvaluator.EvaluateNow(script, vars, null);

            IScriptObject name = vars["NAME"]; // Variable names are case-insensitive.
            IScriptObject x = vars["x"];
            IScriptObject b = vars["b"];

            System.Diagnostics.Debugger.Break(); // check result from above.
        }

        private void btnCustomObjectExample_Click(object sender, EventArgs e)
        {
            // This example demonstrates using custom script objects and reusing an existing ScriptEvaluator instance for better performance.

            System.Diagnostics.Debugger.Break();

            ScriptObjectTypeInfoCollection types = new ScriptObjectTypeInfoCollection();
            types.Add(typeof(ScriptFibonacci), "Fibonacci");
            types.Add(typeof(ScriptPerson), "Person");

            ScriptEvaluator eval = new ScriptEvaluator(); // reusing an instance of ScriptEvaluator provides better performance.

            string script1 = "s=\"\"; for (i=0; i<10; i++) s = s + Fibonacci.Calculate(i) + \", \"; return s;";
            IScriptObject result1 = eval.Evaluate(script1, types);

            string script2 = "p = new Person(\"Sam\", 10); p.Age = p.Age + 2; return p.GetInfo();";
            IScriptObject result2 = eval.Evaluate(script2, types);

            System.Diagnostics.Debugger.Break(); // check results from above.
        }

        private void btnTest_Click(object sender, EventArgs e)
        {
            // There is currently no support for NUnit or MS Test but the following function has many test cases.

            System.Diagnostics.Debugger.Break();

            ScriptEvaluator.Test();
        }
    }


    [ScriptObjectClass("Fibonacci Example", "A sample custom script object.")]
    public class ScriptFibonacci : ScriptObject
    {
        [ScriptObjectMethod]
        public static ScriptNumber Calculate(ScriptNumber x)
        {
            return new ScriptNumber(fibonacci((int)x));
        }

        static int fibonacci(int x)
        {
            if (x == 0 || x == 1)
                return x;
            return fibonacci(x - 1) + fibonacci(x - 2);
        }
    }


    [ScriptObjectClass("Person Example", "A sample custom script object.")]
    public class ScriptPerson : ScriptObject
    {
        private string _name;
        private int _age;

        [ScriptObjectConstructor]
        public ScriptPerson(ScriptString name, ScriptNumber age)
        {
            _name = (string)name;
            _age = (int)age;
        }

        [ScriptObjectProperty]
        public ScriptString Name
        {
            get { return new ScriptString(_name); }
            set { _name = (string)value; }
        }

        [ScriptObjectProperty]
        public ScriptNumber Age
        {
            get { return new ScriptNumber(_age); }
            set { _age = (int)value; }
        }

        [ScriptObjectMethod]
        public ScriptString GetInfo()
        {
            return new ScriptString(_name + " is " + _age + " years old.");
        }
    }
}

